/*
 * Copyright 2011 Clean GWT
 * 
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
 * in compliance with the License. You may obtain a copy of the License at
 * 
 * http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software distributed under the License
 * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
 * or implied. See the License for the specific language governing permissions and limitations under
 * the License.
 */
package com.cleangwt.bootstrap.client.ui;

import com.cleangwt.bootstrap.client.style.Panels;
import com.cleangwt.bootstrap.client.style.Styles;
import com.cleangwt.uibinder.client.TemplateSupport;
import com.cleangwt.user.client.Elements;
import com.google.gwt.dom.client.DivElement;
import com.google.gwt.dom.client.Document;
import com.google.gwt.dom.client.Element;
import com.google.gwt.user.client.ui.ComplexPanel;
import com.google.gwt.user.client.ui.HTML;
import com.google.gwt.user.client.ui.Widget;

/**
 * The collapsible components like accordions and navigation.
 * 
 * @author Jess
 * @version 1.0
 * @since 1.0
 * @see http://getbootstrap.com/javascript/#collapse
 */
public class Collapse extends ComplexPanel {

  /**
   * Creates a collapse that wraps an existing &lt;div&gt; element of template.
   * 
   * @param template the template
   * @param element the element to be wrapped
   */
  public static Collapse wrap(TemplateSupport template, Element element) {
    Collapse widget = new Collapse(element);
    template.wrap(widget);
    return widget;
  }

  /**
   * Creates a input group
   */
  public Collapse() {
    this.setElement(Document.get().createDivElement());
    this.getElement().setId(Document.get().createUniqueId());
    this.setStyleName(Panels.PANEL_GROUP_STYLE);
  }

  /**
   * This constructor may be used by subclasses to explicitly use an existing element. This element
   * must be a &lt;div&gt; element.
   * 
   * @param element the element to be used
   */
  protected Collapse(Element element) {
    assert element.getTagName().equalsIgnoreCase(DivElement.TAG);
    this.setElement(element);
  }

  /**
   * Adds an item with header and content html.
   * 
   * @param header the header
   * @param html the html
   */
  public void addItem(String header, String html) {
    addItem(header, new HTML(html));
  }

  /**
   * Adds an item with header and content widget.
   * 
   * @param header the header
   * @param content the content widget
   */
  public void addItem(String header, Widget content) {
    Element item = Document.get().createDivElement();
    Element heading = Document.get().createDivElement();
    Element toggle = Document.get().createAnchorElement();
    Element collapse = Document.get().createDivElement();
    Element body = Document.get().createDivElement();
    String collapseId = Document.get().createUniqueId();

    this.getElement().appendChild(item);
    item.setClassName(Panels.PANEL_STYLE);
    item.addClassName(Panels.DEFAULT_STYLE);

    item.appendChild(heading);
    heading.setClassName(Panels.HEADING_STYLE);
    heading.appendChild(toggle);

    toggle.setInnerHTML(header);
    toggle.setAttribute(DataModel.DATA_TOGGLE, DataModel.TOGGLE_COLLAPSE);
    toggle.setAttribute(DataModel.DATA_PARENT, getElement().getId());
    toggle.setAttribute("href", "#" + collapseId);

    item.appendChild(collapse);
    collapse.setId(collapseId);
    collapse.setClassName(Panels.COLLAPSE_STYLE);
    collapse.addClassName(Styles.COLLAPSE);
    collapse.appendChild(body);
    body.setClassName(Panels.BODY_STYLE);
    this.add(content, body);

    setToggle(getElement(), collapse);
  }

  /**
   * Shows or hide the element of the given index.
   * 
   * @param index the element index
   */
  public void toggle(int index) {
    Element collapse =
        Elements.getByClass((Element) this.getElement().getChild(index), Panels.COLLAPSE_STYLE);
    toggle(collapse);
  }

  /**
   * Shows the element of the given index.
   * 
   * @param index the element index
   */
  public void show(int index) {
    Element collapse =
        Elements.getByClass((Element) this.getElement().getChild(index), Panels.COLLAPSE_STYLE);
    show(collapse);
  }

  /**
   * Hides the element of the given index.
   * 
   * @param index the element index
   */
  public void hide(int index) {
    Element collapse =
        Elements.getByClass((Element) this.getElement().getChild(index), Panels.COLLAPSE_STYLE);
    hide(collapse);
  }

  private static native void toggle(Element item) /*-{
                                                  $wnd.jQuery(item).collapse('toggle');
                                                  }-*/;

  private static native void show(Element item) /*-{
                                                $wnd.jQuery(item).collapse('show');
                                                }-*/;

  private static native void hide(Element item) /*-{
                                                $wnd.jQuery(item).collapse('hide');
                                                }-*/;

  private static native void setToggle(Element parent, Element toggle) /*-{
                                                                       $wnd.jQuery(toggle).collapse({
                                                                       parent : parent,
                                                                       toggle : false
                                                                       });
                                                                       }-*/;

}
